<template>
  <div
    class="editor"
    :style="{ width: editorWidth, height: editorHeight }"
    @contextmenu="handleContextMenu"
    @mousedown="handleMouseDownArea"
    @drop="handlerDrop"
    @dragover="handlerDragOver"
  >
    <!-- 网格线 -->
    <Grid />
    <!-- 画布上的组件 @mousemove="handleMouseMove" @mouseup="handleMouseUp"  @mousedown="handleMouseDownComponent($event, index)" -->
    <Shape
      class="shape"
      v-for="(item, index) in componentData"
      :key="item.id"
      :default-style="item.style"
      :element="item"
      :zIndex="index"
      :style="getShapeStyle(item.style)"
      :active="item.id === curComponent.id"
    >
      <component
        class="component"
        v-if="item.type == 'input'"
        :placeholder="item.propValue"
        :style="getStyle(item.style)"
        :is="item.component"
      />
      <component
        class="component"
        v-if="item.type == 'button'"
        :style="getStyle(item.style)"
        :is="item.component"
      >
        {{ item.propValue }}</component
      >
    </Shape>
    <!-- 右击展示的菜单 -->
    <ContextMenu />
  </div>
</template>

<script>
import ContextMenu from "./ContextMenu.vue";
import Shape from "./Shape.vue";
import componentList from "@/utils/components-list";
import Grid from "./Grid.vue";
import { getStyle, getShapeStyle } from "@/utils/style";
import { mapState } from "vuex";
import { nanoid } from "nanoid";
import { mapGetters } from "vuex";
export default {
  data() {
    return {
      coordinates: {
        //当前拖动组件的坐标，相对于画布左上角作绝对定位
        top: 0,
        left: 0,
      },
      top: 0,
      left: 0,
      isMove: false,
      curIndex: -1,
    };
  },
  computed: {
    ...mapState({
      componentData: (state) => state.component.componentData || [],
      curComponent: (state) => state.menu.curComponent || {},
    }),
    ...mapGetters(["editorWidth", "editorHeight"]),
  },
  components: {
    Grid,
    Shape,
    ContextMenu,
  },
  methods: {
    getShapeStyle,
    getStyle,
    /**
     * 右击编辑区触发的事件,弹出菜单栏
     */
    handleContextMenu(e) {
      e.stopPropagation();
      e.preventDefault();
      let x = e.offsetX;
      let y = e.offsetY;
      let curComponent = this.curComponent;
      if (Object.keys(curComponent).length != 0) {
        //如果选中了当前组件，x,y的位置将会相对于当前组件
        x += curComponent.style.left - curComponent.style.width / 2;
        y += curComponent.style.top - curComponent.style.height / 2;
      }
      this.$store.commit("SHOW_MENU", { x, y });
    },
    /**
     *  单击编辑区触发的事件
     */
    handleMouseDownArea(e) {
      this.$store.commit("HIDDEN_MENU"); //关闭菜单
      this.$store.commit("SELECT_CUR_COMPONENT"); //取消选中当前组件
    },
    /**
     * 结束拖拽时触发的事件
     */
    handlerDrop(e) {
      e.stopPropagation();
      e.preventDefault();
      let componentItem = componentList[e.dataTransfer.getData("index")];
      //将保存的坐标信息赋给组件
      componentItem.style.top = this.coordinates.top;
      componentItem.style.left = this.coordinates.left;
      componentItem.id = nanoid();
      // 将组件渲染到画布上
      this.$store.commit("ADD_COMPONENT", componentItem);
      // 将组件的坐标恢复默认值
      this.changeCoordinate();
    },
    /**
     * 在画布上滑动触发的事件
     */
    handlerDragOver(e) {
      e.stopPropagation();
      e.preventDefault();
      this.changeCoordinate(e.offsetX, e.offsetY);
    },
    /**
     * 改变当前拖动组件的位置(待优化，该函数执行频率非常高)
     */
    changeCoordinate(x = 0, y = 0) {
      this.coordinates.top = y;
      this.coordinates.left = x;
    },
  },
};
</script>

<style lang="scss" scoped>
.editor {
  background: #fff;
  margin: auto;
  position: relative;
  box-shadow: 0 0 5px #ccc;
  top: 50%;
  transform: translate(0, -50%);
  overflow: hidden;
  .component :hover {
    border: #59c7f9 1px solid;
  }
}
</style>
